//! service_manager.rs 单元测试
//! 
//! 测试服务管理器的功能，验证：
//! 1. 服务管理器的创建和配置
//! 2. 服务组件的添加和移除
//! 3. 服务生命周期的管理
//! 4. 健康检查和诊断功能
//! 5. 并发安全的服务管理
//! 6. 错误处理和恢复机制

use redis_rs2::server::service_manager::*;
use redis_rs2::server::enhanced_traits::*;
use redis_rs2::server::event_publisher::create_default_event_publisher;
use redis_rs2::storage::RedisServerMode;
use tokio_test;
use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait;

// 复用enhanced_traits_test中的Mock实现
use super::enhanced_traits_test::{
    MockServerConfig, MockServiceLifecycle, MockEventPublisher
};

// =============================================================================
// 额外的Mock实现
// =============================================================================

/// Mock健康检查服务 - 用于测试HealthCheck trait
#[derive(Debug)]
struct MockHealthCheckService {
    pub name: String,
    pub is_running: std::sync::Arc<std::sync::atomic::AtomicBool>,
    pub health_status: HealthStatus,
    pub should_fail_health_check: bool,
}

impl MockHealthCheckService {
    pub fn new(name: String, health_status: HealthStatus) -> Self {
        Self {
            name,
            is_running: Arc::new(std::sync::atomic::AtomicBool::new(false)),
            health_status,
            should_fail_health_check: false,
        }
    }
    
    pub fn with_health_check_failure(mut self) -> Self {
        self.should_fail_health_check = true;
        self
    }
}

#[async_trait]
impl ServiceLifecycle for MockHealthCheckService {
    fn service_name(&self) -> &'static str {
        Box::leak(self.name.clone().into_boxed_str())
    }
    
    async fn start(&mut self) -> std::io::Result<()> {
        self.is_running.store(true, std::sync::atomic::Ordering::Relaxed);
        Ok(())
    }
    
    async fn stop(&mut self) -> std::io::Result<()> {
        self.is_running.store(false, std::sync::atomic::Ordering::Relaxed);
        Ok(())
    }
    
    fn is_running(&self) -> bool {
        self.is_running.load(std::sync::atomic::Ordering::Relaxed)
    }
    
    async fn graceful_shutdown(&mut self, _timeout_secs: u64) -> std::io::Result<()> {
        self.stop().await
    }
}

#[async_trait]
impl HealthCheck for MockHealthCheckService {
    async fn health_check(&self) -> Result<HealthStatus, String> {
        if self.should_fail_health_check {
            return Err("Mock health check failure".to_string());
        }
        
        if !self.is_running() {
            return Ok(HealthStatus::Unhealthy("Service not running".to_string()));
        }
        
        Ok(self.health_status.clone())
    }
    
    async fn diagnostics(&self) -> Vec<DiagnosticInfo> {
        vec![
            DiagnosticInfo {
                component: self.name.clone(),
                status: if self.is_running() { "Running" } else { "Stopped" }.to_string(),
                details: Some("Mock health check service".to_string()),
            }
        ]
    }
}

// =============================================================================
// 单元测试
// =============================================================================

#[cfg(test)]
mod service_manager_creation_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_service_manager_creation() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(create_default_event_publisher().await);
        let manager = ServiceManager::new(config, event_publisher);
        
        assert_eq!(manager.service_count(), 0);
        assert!(!manager.is_running());
        assert_eq!(manager.service_names().len(), 0);
    }
    
    #[tokio::test]
    async fn test_service_manager_add_remove_services() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(create_default_event_publisher().await);
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加服务
        let service1 = Box::new(MockServiceLifecycle::new("Service1".to_string()));
        let service2 = Box::new(MockServiceLifecycle::new("Service2".to_string()));
        
        manager.add_service(service1);
        assert_eq!(manager.service_count(), 1);
        
        manager.add_service(service2);
        assert_eq!(manager.service_count(), 2);
        
        let service_names = manager.service_names();
        assert!(service_names.contains(&"Service1"));
        assert!(service_names.contains(&"Service2"));
        
        // 移除服务
        let removed = manager.remove_service("Service1");
        assert!(removed.is_some());
        assert_eq!(manager.service_count(), 1);
        
        // 移除不存在的服务
        let not_removed = manager.remove_service("NonExistent");
        assert!(not_removed.is_none());
        assert_eq!(manager.service_count(), 1);
    }
}

#[cfg(test)]
mod service_manager_lifecycle_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_service_manager_start_stop_success() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher.clone());
        
        // 添加服务
        let service1 = Box::new(MockServiceLifecycle::new("Service1".to_string()));
        let service2 = Box::new(MockServiceLifecycle::new("Service2".to_string()));
        
        manager.add_service(service1);
        manager.add_service(service2);
        
        // 启动服务管理器
        assert!(manager.start().await.is_ok());
        assert!(manager.is_running());
        
        // 验证事件发布
        let published_events = event_publisher.get_published_events();
        assert!(published_events.len() >= 2); // Starting 和 Started 事件
        
        // 停止服务管理器
        assert!(manager.stop().await.is_ok());
        assert!(!manager.is_running());
    }
    
    #[tokio::test]
    async fn test_service_manager_start_failure_cleanup() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher.clone());
        
        // 添加一个正常服务和一个失败服务
        let service1 = Box::new(MockServiceLifecycle::new("Service1".to_string()));
        let service2 = Box::new(MockServiceLifecycle::new("Service2".to_string())
            .with_start_failure());
        
        manager.add_service(service1);
        manager.add_service(service2);
        
        // 启动应该失败
        assert!(manager.start().await.is_err());
        assert!(!manager.is_running());
        
        // 验证错误事件发布
        let published_events = event_publisher.get_published_events();
        assert!(!published_events.is_empty());
    }
    
    #[tokio::test]
    async fn test_service_manager_graceful_shutdown() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加服务
        let service = Box::new(MockServiceLifecycle::new("TestService".to_string()));
        manager.add_service(service);
        
        // 启动
        assert!(manager.start().await.is_ok());
        assert!(manager.is_running());
        
        // 优雅关闭
        assert!(manager.graceful_shutdown(5).await.is_ok());
        assert!(!manager.is_running());
    }
    
    #[tokio::test]
    async fn test_service_manager_restart() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        let service = Box::new(MockServiceLifecycle::new("TestService".to_string()));
        manager.add_service(service);
        
        // 启动
        assert!(manager.start().await.is_ok());
        assert!(manager.is_running());
        
        // 重启
        assert!(manager.restart().await.is_ok());
        assert!(manager.is_running());
    }
}

#[cfg(test)]
mod service_manager_health_check_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_service_manager_health_check_healthy() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加健康的服务
        let healthy_service = Box::new(MockHealthCheckService::new(
            "HealthyService".to_string(),
            HealthStatus::Healthy,
        ));
        manager.add_service(healthy_service);
        
        // 启动
        assert!(manager.start().await.is_ok());
        
        // 健康检查
        let health_status = manager.health_check().await;
        assert!(health_status.is_ok());
        match health_status.unwrap() {
            HealthStatus::Healthy => {},
            _ => panic!("Expected healthy status"),
        }
    }
    
    #[tokio::test]
    async fn test_service_manager_health_check_degraded() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加健康和降级的服务
        let healthy_service = Box::new(MockHealthCheckService::new(
            "HealthyService".to_string(),
            HealthStatus::Healthy,
        ));
        let degraded_service = Box::new(MockHealthCheckService::new(
            "DegradedService".to_string(),
            HealthStatus::Degraded("Performance issues".to_string()),
        ));
        
        manager.add_service(healthy_service);
        manager.add_service(degraded_service);
        
        // 启动
        assert!(manager.start().await.is_ok());
        
        // 健康检查应该返回降级状态
        let health_status = manager.health_check().await;
        assert!(health_status.is_ok());
        match health_status.unwrap() {
            HealthStatus::Degraded(_) => {},
            other => panic!("Expected degraded status, got: {:?}", other),
        }
    }
    
    #[tokio::test]
    async fn test_service_manager_health_check_unhealthy() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加不健康的服务
        let unhealthy_service = Box::new(MockHealthCheckService::new(
            "UnhealthyService".to_string(),
            HealthStatus::Unhealthy("Critical failure".to_string()),
        ));
        manager.add_service(unhealthy_service);
        
        // 启动
        assert!(manager.start().await.is_ok());
        
        // 健康检查应该返回不健康状态
        let health_status = manager.health_check().await;
        assert!(health_status.is_ok());
        match health_status.unwrap() {
            HealthStatus::Unhealthy(_) => {},
            other => panic!("Expected unhealthy status, got: {:?}", other),
        }
    }
    
    #[tokio::test]
    async fn test_service_manager_health_check_not_running() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let manager = ServiceManager::new(config, event_publisher);
        
        // 未启动的服务管理器
        let health_status = manager.health_check().await;
        assert!(health_status.is_ok());
        match health_status.unwrap() {
            HealthStatus::Unhealthy(_) => {},
            other => panic!("Expected unhealthy status for stopped manager, got: {:?}", other),
        }
    }
    
    #[tokio::test]
    async fn test_service_manager_diagnostics() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加支持诊断的服务
        let diagnostic_service = Box::new(MockHealthCheckService::new(
            "DiagnosticService".to_string(),
            HealthStatus::Healthy,
        ));
        manager.add_service(diagnostic_service);
        
        // 启动
        assert!(manager.start().await.is_ok());
        
        // 获取诊断信息
        let diagnostics = manager.diagnostics().await;
        assert!(!diagnostics.is_empty());
        
        // 应该包含ServiceManager自身的诊断信息
        let manager_diag = diagnostics.iter()
            .find(|d| d.component == "ServiceManager");
        assert!(manager_diag.is_some());
        
        // 应该包含服务的诊断信息
        let service_diag = diagnostics.iter()
            .find(|d| d.component == "DiagnosticService");
        assert!(service_diag.is_some());
    }
}

#[cfg(test)]
mod concurrent_service_manager_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_concurrent_service_manager_creation() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let manager = ConcurrentServiceManager::new(config, event_publisher);
        
        assert_eq!(manager.service_count().await, 0);
        assert!(!manager.is_running());
    }
    
    #[tokio::test]
    async fn test_concurrent_service_manager_add_remove() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let manager = ConcurrentServiceManager::new(config, event_publisher);
        
        // 添加服务
        let service = Box::new(MockServiceLifecycle::new("ConcurrentService".to_string()));
        manager.add_service(service).await;
        assert_eq!(manager.service_count().await, 1);
        
        // 移除服务
        let removed = manager.remove_service("ConcurrentService").await;
        assert!(removed.is_some());
        assert_eq!(manager.service_count().await, 0);
    }
    
    #[tokio::test]
    async fn test_concurrent_service_manager_lifecycle() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ConcurrentServiceManager::new(config, event_publisher);
        
        let service = Box::new(MockServiceLifecycle::new("ConcurrentService".to_string()));
        manager.add_service(service).await;
        
        // 启动
        assert!(manager.start().await.is_ok());
        assert!(manager.is_running());
        
        // 停止
        assert!(manager.stop().await.is_ok());
        assert!(!manager.is_running());
    }
    
    #[tokio::test]
    async fn test_concurrent_service_manager_health_check() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ConcurrentServiceManager::new(config, event_publisher);
        
        let healthy_service = Box::new(MockHealthCheckService::new(
            "ConcurrentHealthyService".to_string(),
            HealthStatus::Healthy,
        ));
        manager.add_service(healthy_service).await;
        
        assert!(manager.start().await.is_ok());
        
        let health_status = manager.health_check().await;
        assert!(health_status.is_ok());
    }
}

#[cfg(test)]
mod service_manager_error_handling_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_service_manager_event_publisher_failure() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new().with_publish_failure());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        let service = Box::new(MockServiceLifecycle::new("TestService".to_string()));
        manager.add_service(service);
        
        // 启动应该成功，即使事件发布失败
        assert!(manager.start().await.is_ok());
        assert!(manager.is_running());
    }
    
    #[tokio::test]
    async fn test_service_manager_partial_service_failure() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加一个成功的服务，一个失败的服务，再一个成功的服务
        let service1 = Box::new(MockServiceLifecycle::new("Service1".to_string()));
        let service2 = Box::new(MockServiceLifecycle::new("Service2".to_string())
            .with_start_failure());
        let service3 = Box::new(MockServiceLifecycle::new("Service3".to_string()));
        
        manager.add_service(service1);
        manager.add_service(service2);
        manager.add_service(service3);
        
        // 启动应该失败，并且应该清理已启动的服务
        assert!(manager.start().await.is_err());
        assert!(!manager.is_running());
    }
    
    #[tokio::test]
    async fn test_service_manager_health_check_failure() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加一个健康检查失败的服务
        let failing_service = Box::new(MockHealthCheckService::new(
            "FailingService".to_string(),
            HealthStatus::Healthy,
        ).with_health_check_failure());
        manager.add_service(failing_service);
        
        assert!(manager.start().await.is_ok());
        
        // 健康检查应该返回不健康状态
        let health_status = manager.health_check().await;
        assert!(health_status.is_ok());
        match health_status.unwrap() {
            HealthStatus::Unhealthy(_) => {},
            other => panic!("Expected unhealthy status due to health check failure, got: {:?}", other),
        }
    }
}

#[cfg(test)]
mod service_manager_performance_tests {
    use super::*;
    use std::time::Instant;
    
    #[tokio::test]
    async fn test_service_manager_startup_performance() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let mut manager = ServiceManager::new(config, event_publisher);
        
        // 添加多个服务
        for i in 0..100 {
            let service = Box::new(MockServiceLifecycle::new(format!("Service{}", i)));
            manager.add_service(service);
        }
        
        let start_time = Instant::now();
        assert!(manager.start().await.is_ok());
        let elapsed = start_time.elapsed();
        
        // 启动100个服务应该在合理时间内完成（比如1秒）
        assert!(elapsed < Duration::from_secs(1), "Startup took too long: {:?}", elapsed);
        assert!(manager.is_running());
        assert_eq!(manager.service_count(), 100);
    }
    
    #[tokio::test]
    async fn test_service_manager_concurrent_operations() {
        let config = Box::new(MockServerConfig {
            mode: RedisServerMode::Standalone,
            bind_address: "127.0.0.1:6379".to_string(),
            should_validate: true,
        });
        
        let event_publisher = Arc::new(MockEventPublisher::new());
        let manager = Arc::new(ConcurrentServiceManager::new(config, event_publisher));
        
        // 并发添加服务
        let mut handles = Vec::new();
        for i in 0..50 {
            let manager_clone = Arc::clone(&manager);
            let handle = tokio::spawn(async move {
                let service = Box::new(MockServiceLifecycle::new(format!("ConcurrentService{}", i)));
                manager_clone.add_service(service).await;
            });
            handles.push(handle);
        }
        
        // 等待所有添加操作完成
        for handle in handles {
            handle.await.unwrap();
        }
        
        assert_eq!(manager.service_count().await, 50);
    }
}